//
// chat_server.cpp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#include <algorithm>
#include <cstdlib>
#include <deque>
#include <iostream>
#include <list>
#include <set>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
//#include "chat_message.h"
#include "quaternion.h"

#include "server_region.h"
#include "node.h"
#include "wid.h"
#include "errors.h"
#include "listener.h"

#include <sstream>
#include <iomanip>

using boost::asio::ip::tcp;

class chat_server {
public:
	chat_server(Wonderland::ServerRegion *region, boost::asio::io_service& io_service, const tcp::endpoint& endpoint) 
		: region_(region), io_service_(io_service), acceptor_(io_service, endpoint) {
		prepareNewConnection();
	}

	/*
	 * @brief Allocate a new session and wait for someone to connect
	 */
	void prepareNewConnection(){
		Wonderland::Listener* listener = new Wonderland::Listener(io_service_, region_);

		acceptor_.async_accept(listener->socket(),
			boost::bind(&chat_server::handle_accept, this, listener, boost::asio::placeholders::error)
		);
	}
	
	/*
	 * @brief Accept a connection and prepare for the next one
	 */
	void handle_accept(Wonderland::Listener* listener, const boost::system::error_code& error){
		if (!error){
			listener->acceptConnection();

			prepareNewConnection();
		}
	}

private:
	boost::asio::io_service& io_service_;
	tcp::acceptor acceptor_;
	Wonderland::ServerRegion* region_;
};

typedef boost::shared_ptr<chat_server> chat_server_ptr;
typedef std::list<chat_server_ptr> chat_server_list;

//----------------------------------------------------------------------

int main(int argc, char* argv[]){

	Wonderland::Wid owner("ben@...");
	Wonderland::Wid agent("ben@.../viewer");
	
//	try{
//		int i;
//
//		for(i=0;i<100;i++){
//			std::stringstream x;
//			x << "<node guid='" << i << "' owner='ben@' agent='ben@' position='1,2,3' rotation='0,0,0,0' scale='1,1,1' />";
//			
//			r.addNode(new Wonderland::Node(x.str()));
//		}
//

//	}catch(Wonderland::Errors::Fatal err){
//		std::cout << "Fatal wonderland error.." << std::endl << "  " << err.what() << "." << std::endl;
//	}

	// Sleep so we can find leaks
//	std::cout << std::endl << "Finished - you can detect leaks now..." << std::endl;
//	while (1) sleep(60);
	
//  try
//  {
    if (argc < 2){
      std::cerr << "Usage: server <port> [scene.xml]\n";
      return 1;
    }

	std::cout << "Wonderland server starting...\n";

    boost::asio::io_service io_service;

	Wonderland::ServerRegion r(&io_service);
	
	if(argc>2){
		r.load(std::string(argv[2]));
	}else{

		int i;

		for(i=0;i<3;i++){
			std::stringstream x;
			x << "<node guid='" << i << "' owner='ben@' agent='ben@' position='1,2,3' rotation='0,0,0,0' scale='1,1,1' />";
			
			r.addNode(new Wonderland::Node(x.str()));
		}
	}

	r.save("/tmp/scene.xml");

    chat_server_list servers;
	int i = 1;

		std::cout << "  * Listening on port " << argv[i] << "\n";

		using namespace std; // For atoi.

		tcp::endpoint endpoint(tcp::v4(), atoi(argv[i]));
		chat_server_ptr server(new chat_server(&r, io_service, endpoint));
		servers.push_back(server);

	io_service.run();
	
//  }
//  catch (std::exception& e)
//  {
//    std::cerr << "Exception: " << e.what() << "\n";
//  }

  return 0;
}